/**
 * Test Helper Functions for TaskMaster E2E Tests
 * AceFlow v3.0 - E2E Testing Phase
 */

import { expect } from '@playwright/test';
import { TEST_CONSTANTS } from './test-data.js';

/**
 * Wait for page to be fully loaded
 * @param {Page} page - Playwright page object
 */
export async function waitForPageLoad(page) {
  await page.waitForLoadState('networkidle');
  await page.waitForLoadState('domcontentloaded');
}

/**
 * Login user through UI
 * @param {Page} page - Playwright page object
 * @param {string} username - Username
 * @param {string} password - Password
 */
export async function loginUser(page, username, password) {
  // Navigate to login page if not already there
  if (!page.url().includes('/login')) {
    await page.goto('/login');
  }

  // Fill login form
  await page.fill('input[name="username"]', username);
  await page.fill('input[name="password"]', password);

  // Click login button
  await page.click('button[type="submit"]');

  // Wait for navigation or success message
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_MEDIUM);

  // Check if login was successful
  const currentUrl = page.url();
  if (currentUrl.includes('/login')) {
    throw new Error('Login failed - still on login page');
  }
}

/**
 * Register user through UI
 * @param {Page} page - Playwright page object
 * @param {Object} userData - User data object
 */
export async function registerUser(page, userData) {
  // Navigate to register page
  await page.goto('/register');

  // Fill registration form
  await page.fill('input[name="username"]', userData.username);
  await page.fill('input[name="email"]', userData.email);
  await page.fill('input[name="password"]', userData.password);

  // Click register button
  await page.click('button[type="submit"]');

  // Wait for navigation or success message
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_MEDIUM);

  // Check if registration was successful
  const currentUrl = page.url();
  if (currentUrl.includes('/register')) {
    // Check for error message
    const errorMessage = await page.textContent('.error-message, .alert-danger');
    if (errorMessage) {
      throw new Error(`Registration failed: ${errorMessage}`);
    }
    throw new Error('Registration failed - still on register page');
  }
}

/**
 * Logout user
 * @param {Page} page - Playwright page object
 */
export async function logoutUser(page) {
  // Click logout button/link
  const logoutButton = page.locator('a[href*="logout"], button[data-testid*="logout"]').first();
  await logoutButton.click();

  // Wait for logout to complete
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_MEDIUM);
}

/**
 * Create a task through UI
 * @param {Page} page - Playwright page object
 * @param {Object} taskData - Task data object
 */
export async function createTask(page, taskData) {
  // Click add task button
  const addButton = page.locator('button[data-testid*="add"], a[href*="new"]').first();
  await addButton.click();

  // Wait for form to appear
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_SHORT);

  // Fill task form
  await page.fill('input[name="title"]', taskData.title);
  await page.fill('textarea[name="description"]', taskData.description);

  // Fill due date if present
  const dueDateInput = page.locator('input[name="due_date"], input[type="date"]');
  if (await dueDateInput.isVisible()) {
    await dueDateInput.fill(taskData.dueDate.split('T')[0]);
  }

  // Select priority if present
  const prioritySelect = page.locator('select[name="priority"]');
  if (await prioritySelect.isVisible()) {
    await prioritySelect.selectOption(taskData.priority.toString());
  }

  // Click save button
  const saveButton = page.locator('button[type="submit"], button[data-testid*="save"]').first();
  await saveButton.click();

  // Wait for task to be created
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_MEDIUM);
}

/**
 * Edit a task through UI
 * @param {Page} page - Playwright page object
 * @param {string} taskTitle - Title of task to edit
 * @param {Object} newTaskData - New task data
 */
export async function editTask(page, taskTitle, newTaskData) {
  // Find and click edit button for the task
  const taskItem = page.locator(`[data-testid*="task"]:has-text("${taskTitle}")`).first();
  const editButton = taskItem.locator('button[data-testid*="edit"], a[data-testid*="edit"]').first();
  await editButton.click();

  // Wait for edit form
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_SHORT);

  // Update task data
  if (newTaskData.title) {
    await page.fill('input[name="title"]', newTaskData.title);
  }
  if (newTaskData.description) {
    await page.fill('textarea[name="description"]', newTaskData.description);
  }
  if (newTaskData.priority) {
    const prioritySelect = page.locator('select[name="priority"]');
    if (await prioritySelect.isVisible()) {
      await prioritySelect.selectOption(newTaskData.priority.toString());
    }
  }

  // Click save button
  const saveButton = page.locator('button[type="submit"], button[data-testid*="save"]').first();
  await saveButton.click();

  // Wait for update to complete
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_MEDIUM);
}

/**
 * Delete a task through UI
 * @param {Page} page - Playwright page object
 * @param {string} taskTitle - Title of task to delete
 */
export async function deleteTask(page, taskTitle) {
  // Find and click delete button for the task
  const taskItem = page.locator(`[data-testid*="task"]:has-text("${taskTitle}")`).first();
  const deleteButton = taskItem.locator('button[data-testid*="delete"]').first();
  await deleteButton.click();

  // Confirm deletion if confirmation dialog appears
  const confirmButton = page.locator('button[data-testid*="confirm"], .modal button.btn-danger').first();
  if (await confirmButton.isVisible()) {
    await confirmButton.click();
  }

  // Wait for deletion to complete
  await page.waitForTimeout(TEST_CONSTANTS.WAIT_MEDIUM);
}

/**
 * Check if task exists in the list
 * @param {Page} page - Playwright page object
 * @param {string} taskTitle - Task title to check
 * @returns {boolean} True if task exists
 */
export async function taskExists(page, taskTitle) {
  const taskItem = page.locator(`[data-testid*="task"]:has-text("${taskTitle}")`);
  return await taskItem.isVisible();
}

/**
 * Get task count from the page
 * @param {Page} page - Playwright page object
 * @returns {number} Number of tasks
 */
export async function getTaskCount(page) {
  const taskItems = page.locator('[data-testid*="task"]');
  return await taskItems.count();
}

/**
 * Wait for element to be visible with timeout
 * @param {Page} page - Playwright page object
 * @param {string} selector - CSS selector
 * @param {number} timeout - Timeout in milliseconds
 */
export async function waitForElement(page, selector, timeout = TEST_CONSTANTS.WAIT_MEDIUM) {
  await page.waitForSelector(selector, { timeout });
}

/**
 * Take screenshot for debugging
 * @param {Page} page - Playwright page object
 * @param {string} name - Screenshot name
 */
export async function takeScreenshot(page, name) {
  await page.screenshot({ path: `screenshots/${name}.png`, fullPage: true });
}

/**
 * Clear browser storage and cookies
 * @param {Page} page - Playwright page object
 */
export async function clearBrowserData(page) {
  await page.context().clearCookies();
  await page.evaluate(() => {
    localStorage.clear();
    sessionStorage.clear();
  });
}

/**
 * Setup test user by registering through API
 * @param {Object} userData - User data
 */
export async function setupTestUser(userData) {
  // This would typically call the API directly to set up test data
  // For now, we'll use the UI registration
  const { chromium } = await import('playwright');
  const browser = await chromium.launch();
  const page = await browser.newPage();

  try {
    await page.goto('http://localhost:5173/register');
    await registerUser(page, userData);
  } finally {
    await browser.close();
  }
}

/**
 * Cleanup test data
 * @param {string} username - Username to cleanup
 */
export async function cleanupTestData(username) {
  // This would typically call the API to clean up test data
  // For now, we'll skip this as the test database is recreated each time
  console.log(`Cleanup test data for user: ${username}`);
}

/**
 * Assert that user is logged in
 * @param {Page} page - Playwright page object
 */
export async function assertUserLoggedIn(page) {
  // Check for logout button or user info
  const logoutButton = page.locator('a[href*="logout"], button[data-testid*="logout"]');
  await expect(logoutButton).toBeVisible();

  // Check that we're not on login page
  const currentUrl = page.url();
  expect(currentUrl).not.toContain('/login');
}

/**
 * Assert that user is logged out
 * @param {Page} page - Playwright page object
 */
export async function assertUserLoggedOut(page) {
  // Check for login button
  const loginButton = page.locator('a[href*="login"], button[data-testid*="login"]');
  await expect(loginButton).toBeVisible();

  // Check that we're on login page or homepage
  const currentUrl = page.url();
  expect(currentUrl).toMatch(/\/$|\/login$/);
}

/**
 * Assert success message is displayed
 * @param {Page} page - Playwright page object
 * @param {string} message - Expected message text
 */
export async function assertSuccessMessage(page, message = '') {
  const successElement = page.locator('.alert-success, .success-message, [data-testid*="success"]');
  await expect(successElement).toBeVisible();

  if (message) {
    await expect(successElement).toContainText(message);
  }
}

/**
 * Assert error message is displayed
 * @param {Page} page - Playwright page object
 * @param {string} message - Expected message text
 */
export async function assertErrorMessage(page, message = '') {
  const errorElement = page.locator('.alert-danger, .error-message, [data-testid*="error"]');
  await expect(errorElement).toBeVisible();

  if (message) {
    await expect(errorElement).toContainText(message);
  }
}
